home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 November / macformat-018.iso / Utility Spectacular / Developer / macgambit-20-compiler-src-p2 / Interp⁄Comp (.scm) / target-m68000-2.scm < prev    next >
Encoding:
Text File  |  1994-07-26  |  61.2 KB  |  1,823 lines  |  [TEXT/gamI]

  1. ;==============================================================================
  2.  
  3. ; file: "target-m68000-2.scm"
  4.  
  5. ;------------------------------------------------------------------------------
  6. ;
  7. ; Object file creation (for M680x0)
  8. ; ---------------------------------
  9.  
  10. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  11.  
  12. ; An object file is a collection of Scheme objects.  The objects in the file
  13. ; are named by their position in the file.  The first object in the file is
  14. ; object number 0, the second is object number 1, etc.  Object number 0 is the
  15. ; startup procedure (it must be a procedure object).  It will be called
  16. ; after the file has been loaded.
  17. ;
  18. ; The objects have the same layout as in memory (see below).  However, a prefix
  19. ; appears in front of certain objects to give additional information about
  20. ; the given object.  The prefix word 1 informs the loader that the following
  21. ; procedure object is a primitive procedure, and the prefix word 2 indicates
  22. ; a normal procedure.  Pairs have a word prefix of 3.
  23. ;
  24. ; Object pointers contained in these objects also follow the same format
  25. ; as in memory with the following additions:
  26. ;
  27. ;  11111111111111100nnnnnnnnnnnn111 = pointer to object number 'n'
  28. ;  11111111111111101xxxxxxxxxxxx111 = pointer to interned symbol number 'x'
  29. ;  11111111111111110xxxxxxxxxxxx111 = pointer to primitive procedure number 'x'
  30. ;
  31. ; Finally, procedure objects have a special structure that is needed to
  32. ; describe the code part of the procedure.  The code part of a procedure
  33. ; is made up of a sequence of blocks.  Each block is preceded by a word tag 't'
  34. ; that specifies how to treat the block:
  35. ;
  36. ;  t > 0000000000000000, quoted code (the following 't' words are loaded as is)
  37. ;  t = 0000000000000000, padding (ignored)
  38. ;  t = 1000000000000000, end of code (constant part of procedure follows)
  39. ;  t = 1000000000000001, M68020 processor specific instruction marker
  40. ;  t = 1000000000000010, M68881 processor specific instruction marker
  41. ;  t = 1000000000000011, statistics reference (followed by statistics counters)
  42. ;  t = 1001nnnnnnnnnnnn, local procedure ref (followed by offset to entry)
  43. ;  t = 1010xxxxxxxxxxxx, global var ref to var number 'x'
  44. ;  t = 1011xxxxxxxxxxxx, global var set to var number 'x'
  45. ;  t = 1100xxxxxxxxxxxx, global var ref jump to var number 'x'
  46. ;  t = 1101xxxxxxxxxxxx, primitive procedure ref to prim proc number 'x' (followed by offset to entry)
  47. ;
  48. ; In this description, 'xxxxxxxxxxxx' represents an index into a symbol table
  49. ; local to the object file.  The special value of all 1's indicates that the
  50. ; tag is followed by a null terminated string to be added to the local symbol
  51. ; table (it is built as the file is loaded and is initially empty).
  52.  
  53. (define ofile-version-major     3)
  54. (define ofile-version-minor     0)
  55.  
  56. (define prim-proc-prefix        1)
  57. (define user-proc-prefix        2)
  58. (define pair-prefix             3)
  59.  
  60. (define local-object-bits       #x-1fff9) ; 11111111111111100000000000000111
  61. (define symbol-object-bits      #x-17ff9) ; 11111111111111101000000000000111
  62. (define prim-proc-object-bits   #x-0fff9) ; 11111111111111110000000000000111
  63.  
  64. (define padding-tag             #x0000)
  65. (define end-of-code-tag         #x8000)
  66. (define M68020-proc-code-tag    #x8001)
  67. (define M68881-proc-code-tag    #x8002)
  68. (define stat-tag                #x8003)
  69.  
  70. (define local-proc-ref-tag      #x9000)
  71. (define global-var-ref-tag      #xa000)
  72. (define global-var-set-tag      #xb000)
  73. (define global-var-ref-jump-tag #xc000)
  74. (define prim-proc-ref-tag       #xd000)
  75.  
  76. (define index-mask              #x0fff)
  77.  
  78. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  79.  
  80. ; Interface:
  81. ; ---------
  82.  
  83. (define (ofile.begin! filename add-obj)
  84.   (set! ofile-add-obj add-obj)
  85.   (set! ofile-syms (queue-empty))
  86.   (set! *ofile-port1* (open-output-file (string-append filename ".O")))
  87.   (if ofile-asm?
  88.     (begin
  89.       (set! *ofile-port2* (open-output-file (string-append filename ".asm")))
  90.       (set! *ofile-pos* 0)))
  91.   (ofile-line " .data")
  92.   (ofile-word ofile-version-major)
  93.   (ofile-word ofile-version-minor)
  94.   '())
  95.  
  96. (define (ofile.end!)
  97.   (ofile-line "")
  98.   (close-output-port *ofile-port1*)
  99.   (if ofile-asm?
  100.     (close-output-port *ofile-port2*))
  101.   '())
  102.  
  103. (define *ofile-port1* '())
  104.  
  105. (define *ofile-port2* '())
  106.  
  107. (define *ofile-pos* '())
  108.  
  109. (define ofile-nl char-newline)
  110.  
  111. (define ofile-tab char-tab)
  112.  
  113. (define ofile-asm? '())
  114. (set! ofile-asm? '())
  115.  
  116. (define ofile-stats? '())
  117. (set! ofile-stats? '())
  118.  
  119. (define ofile-add-obj '())
  120. (set! ofile-add-obj '())
  121.  
  122. (define (ofile-word n)
  123.   (let ((n (modulo n #x10000)))
  124.     (if ofile-asm?
  125.       (let ()
  126.  
  127.         (define (ofile-display x)
  128.           (display x *ofile-port2*)
  129.           (cond ((eq? x ofile-nl)
  130.                  (set! *ofile-pos* 0))
  131.                 ((eq? x ofile-tab)
  132.                  (set! *ofile-pos* (* (quotient (+ *ofile-pos* 8) 8) 8)))
  133.                 (else
  134.                  (set! *ofile-pos* (+ *ofile-pos* (string-length x))))))
  135.  
  136.         (if (> *ofile-pos* 64) (ofile-display ofile-nl))
  137.         (if (= *ofile-pos* 0)
  138.           (ofile-display " .word")
  139.           (ofile-display ","))
  140.         (ofile-display ofile-tab)
  141.         (let ((s (make-string 6 #\0)))
  142.           (string-set! s 1 #\x)
  143.           (let loop ((i 5) (n n))
  144.             (if (> n 0)
  145.               (begin
  146.                 (string-set! s i (string-ref "0123456789ABCDEF" (remainder n 16)))
  147.                 (loop (- i 1) (quotient n 16)))))
  148.           (ofile-display s))))
  149.  
  150.     (write-word n *ofile-port1*)))
  151.  
  152. (define (ofile-long x)
  153.   (ofile-word (upper-16bits x))
  154.   (ofile-word x))
  155.  
  156. (define (ofile-string s)
  157.   (let ((len (string-length s)))
  158.     (define (ref i) (if (>= i len) 0 (character-encoding (string-ref s i))))
  159.     (let loop ((i 0))
  160.       (if (< i len)
  161.         (begin
  162.           (ofile-word (+ (* (ref i) 256) (ref (+ i 1))))
  163.           (loop (+ i 2)))))
  164.     (if (= (remainder len 2) 0)
  165.       (ofile-word 0))))
  166.  
  167. (define (ofile-wsym tag name)
  168.   (let ((n (string-pos-in-list name (queue->list ofile-syms))))
  169.     (if n
  170.       (ofile-word (+ tag n))
  171.       (let ((m (length (queue->list ofile-syms))))
  172.         (queue-put! ofile-syms name)
  173.         (ofile-word (+ tag index-mask))
  174.         (ofile-string name)))))
  175.  
  176. (define (ofile-lsym tag name)
  177.   (let ((n (string-pos-in-list name (queue->list ofile-syms))))
  178.     (if n
  179.       (ofile-long (+ tag (* n 8)))
  180.       (let ((m (length (queue->list ofile-syms))))
  181.         (queue-put! ofile-syms name)
  182.         (ofile-long (+ tag (* index-mask 8)))
  183.         (ofile-string name)))))
  184.  
  185. (define (ofile-ref obj)
  186.   (let ((n (obj-encoding obj)))
  187.     (if n
  188.       (ofile-long n)
  189.       (if (symbol-object? obj)
  190.         (begin
  191.           (ofile-lsym symbol-object-bits (symbol->string obj)))
  192.         (let ((m (ofile-add-obj obj)))
  193.           (if m
  194.             (ofile-long (+ local-object-bits (* m 8)))
  195.             (begin
  196.               (ofile-lsym prim-proc-object-bits (proc-obj-name obj)))))))))
  197.  
  198. (define (ofile-prim-proc s)
  199.   (ofile-long prim-proc-prefix)
  200.   (ofile-wsym 0 s)
  201.   (ofile-comment (list "PRIMITIVE PROCEDURE: " s)))
  202.  
  203. (define (ofile-user-proc)
  204.   (ofile-long user-proc-prefix))
  205.  
  206. (define (ofile-line s)
  207.   (if ofile-asm?
  208.     (begin
  209.       (if (> *ofile-pos* 0) (newline *ofile-port2*))
  210.       (display s *ofile-port2*)
  211.       (newline *ofile-port2*)
  212.       (set! *ofile-pos* 0))))
  213.  
  214. (define (ofile-comment l)
  215.   (if ofile-asm?
  216.     (let ()
  217.  
  218.       (define (tab n)
  219.         (let loop ()
  220.           (if (< *ofile-pos* n)
  221.             (begin
  222.               (display ofile-tab *ofile-port2*)
  223.               (set! *ofile-pos* (* (quotient (+ *ofile-pos* 8) 8) 8))
  224.               (loop)))))
  225.  
  226.       (tab 32)
  227.       (display "|" *ofile-port2*)
  228.       (for-each (lambda (x) (display x *ofile-port2*)) l)
  229.       (newline *ofile-port2*)
  230.       (set! *ofile-pos* 0))))
  231.  
  232. (define (ofile-pvm-instr code)
  233.   (if ofile-asm?
  234.     (let ((pvm-instr (code-pvm-instr code))
  235.           (sn (code-slots-needed code)))
  236.       (if (> *ofile-pos* 0) (newline *ofile-port2*))
  237.       (display "                                |**** [" *ofile-port2*)
  238.       (display sn *ofile-port2*)
  239.       (display "] " *ofile-port2*)
  240.       (write-pvm-instr pvm-instr *ofile-port2*)
  241.       (newline *ofile-port2*)
  242.       (set! *ofile-pos* 0))))
  243.  
  244. (define (ofile-stat stat)
  245.  
  246.   (define (->string x)
  247.     (cond ((string? x) x)
  248.           ((symbol-object? x) (symbol->string x))
  249.           ((number? x) (number->string x))
  250.           ((false-object? x) "#f")
  251.           ((eq? x #t) "#t")
  252.           ((null? x) "()")
  253.           ((pair? x)
  254.            (let loop ((l1 (cdr x)) (l2 (list (->string (car x)) "(")))
  255.              (cond ((pair? l1)
  256.                     (loop (cdr l1)
  257.                           (cons (->string (car l1)) (cons " " l2))))
  258.                    ((null? l1)
  259.                     (apply string-append
  260.                            (reverse (cons ")" l2))))
  261.                    (else
  262.                     (apply string-append
  263.                            (reverse (cons ")" (cons (->string l1) (cons " . " l2)))))))))
  264.           (else
  265.            (compiler-internal-error
  266.              "ofile-stat, can't convert to string 'x'" x))))
  267.  
  268.   (ofile-string (->string stat)))
  269.  
  270. (define (upper-16bits x)
  271.   (cond ((>= x 0)           (quotient x #x10000))
  272.         ((>= x (- #x10000)) -1)
  273.         (else               (- (quotient (+ x #x10001) #x10000) 2))))
  274.  
  275. ;-----------------------------------------------------------------------------
  276. ;
  277. ; Object representation:
  278.  
  279. ; Objects are represented using 32 bit values.  When more than 32 bits
  280. ; are needed to represent an object, the 32 bits are actually a pointer
  281. ; to the object in memory.  All memory allocated objects start at an
  282. ; address that is a multiple of 8.
  283. ;
  284. ;
  285. ;                                  28     28
  286. ; * Fixnum (integer in the range -2   .. 2  -1):
  287. ;
  288. ;     encoding = xxxxxxxxxxxxxxxxxxxxxxxxxxxxx000
  289. ;                \------ integer value ------/
  290. ;
  291. ;
  292. ; * Special scalar values and characters:
  293. ;
  294. ;     encoding = xxxxxxxxxxxxxxxxxxxxxxxxxxxxx111
  295. ;                \--   encoding of value   --/
  296. ;   
  297. ;   for example:
  298. ;     000000000000000000000xxxxxxxx111 = character
  299. ;     1xxxxxxxxxxxxxxxxxxxxxxxxxxxx111 = #f, #t, (), eof, ...
  300. ;
  301. ;
  302. ; * Pair (i.e. cons cell):
  303. ;
  304. ;     xxxxxxxxxxxxxxxxxxxxxxxxxxxxx100
  305. ;                     _____________________
  306. ;     xx...xx000 --> |_____________________| cdr     | high
  307. ;                    |_____________________| car     | memory
  308. ;                     <----- 32 bits ----->          V
  309. ;
  310. ;
  311. ; * Future placeholder:
  312. ;
  313. ;     encoding = xxxxxxxxxxxxxxxxxxxxxxxxxxxxx101
  314. ;                     _____________________
  315. ;     xx...xx000 --> |_____________________| value   | high
  316. ;                    |_____________________| lock    | memory
  317. ;                    |_____________________| thunk   V
  318. ;                    |_____________________| queue
  319. ;                     <----- 32 bits ----->
  320. ;
  321. ;
  322. ; * Subtyped objects:
  323. ;
  324. ;     encoding = xxxxxxxxxxxxxxxxxxxxxxxxxxxxx011
  325. ;                     _____________________
  326. ;     xx...xx000 --> |____length____|_type_| header  | high
  327. ;                    |_____________________| \       | memory
  328. ;                    |_____________________|  | data V
  329. ;                    |_____________________| /
  330. ;                     <----- 32 bits ----->
  331. ;
  332. ; 'Length' is a 24 bit field (in the upper part of the header word).  The
  333. ; length must be positive (highest bit = 0) and indicates the length of
  334. ; the data part.  The subtype is in the lower 8 bits of the header word
  335. ; and is encoded as subtype*8.
  336. ;
  337. ;
  338. ; * Procedures:
  339. ;
  340. ;     encoding = xxxxxxxxxxxxxxxxxxxxxxxxxxxxx010
  341. ;                     _____________________
  342. ;     xx...xx000 --> |__length__|__instr1__| \       | high
  343. ;                    |_____________________|  | code | memory
  344. ;                    |_____________________|  |      V
  345. ;                    |_____________________| /
  346. ;                    |_____________________| \
  347. ;                    |_____________________|  | data
  348. ;                    |_____________________| /
  349. ;                     <----- 32 bits ----->
  350. ;
  351. ; There are several types of procedure objects, each with it's own
  352. ; particularities: PROCEDUREs, SUBPROCEDUREs, CLOSUREs and RETURNs.
  353.  
  354. ; Type tags
  355.  
  356. (define type-FIXNUM          0)
  357. (define type-SPECIAL         7)
  358. (define type-PAIR            4)
  359. (define type-WEAK-PAIR       1)
  360. (define type-PLACEHOLDER     5)
  361. (define type-SUBTYPED        3)
  362. (define type-PROCEDURE       2)
  363.  
  364. ; Subtype tags
  365.  
  366. (define subtype-VECTOR       0)
  367. (define subtype-SYMBOL       1)
  368. (define subtype-PORT         2)
  369. (define subtype-RATNUM       3)
  370. (define subtype-CPXNUM       4)
  371. (define subtype-CLOSURE      15)
  372. (define subtype-STRING       16)
  373. (define subtype-BIGNUM       17)
  374. (define subtype-FLONUM       18)
  375.  
  376. ; SPECIAL values:
  377.  
  378. (define data-FALSE           (- #x2020203)) ; Data field for #f
  379. (define data-NULL            (- #x4040405)) ; Data field for ()
  380. (define data-TRUE            -2)            ; Data field for #t
  381. (define data-UNDEF           -3)            ; Data field for undefined object
  382. (define data-UNASS           -4)            ; Data field for unassigned object
  383. (define data-UNBOUND         -5)            ; Data field for unbound object
  384. (define data-EOF             -6)            ; Data field for end-of-file object
  385.  
  386. (define data-max-fixnum      #xfffffff) ; Max fixnum integer
  387. (define data-min-fixnum      (- #x10000000)) ; Min fixnum integer
  388.  
  389. ; Utilities:
  390.  
  391. (define (make-encoding data type)
  392.   (+ (* data 8) type))
  393.  
  394. (define (obj-type obj)
  395.   (cond ((false-object? obj)
  396.          'SPECIAL)
  397.         ((undef-object? obj)
  398.          'SPECIAL)
  399.         ((symbol-object? obj)
  400.          'SUBTYPED)
  401.         ((proc-obj? obj)
  402.          'PROCEDURE)
  403.         ((eq? obj #t)
  404.          'SPECIAL)
  405.         ((null? obj)
  406.          'SPECIAL)
  407.         ((pair? obj)
  408.          'PAIR)
  409.         ((number? obj)
  410.          (if (and (integer? obj) (exact? obj)
  411.                   (>= obj data-min-fixnum) (<= obj data-max-fixnum))
  412.            'FIXNUM
  413.            'SUBTYPED))
  414.         ((char? obj)
  415.          'SPECIAL)
  416.         (else
  417.          'SUBTYPED)))
  418.  
  419. (define (obj-subtype obj)
  420.   (cond ((symbol-object? obj)
  421.          'SYMBOL)
  422.         ((number? obj)
  423.          (cond ((and (integer? obj) (exact? obj))
  424.                 'BIGNUM)
  425.                ((and (rational? obj) (exact? obj))
  426.                 'RATNUM)
  427.                ((and (zero? (imag-part obj)) (exact? (imag-part obj)))
  428.                 'FLONUM)
  429.                (else
  430.                 'CPXNUM)))
  431.         ((vector? obj)
  432.          'VECTOR)
  433.         ((string? obj)
  434.          'STRING)
  435.         (else
  436.          (compiler-internal-error
  437.            "obj-subtype, unknown object 'obj'" obj))))
  438.  
  439. (define (obj-type-tag obj)
  440.   (case (obj-type obj)
  441.     ((FIXNUM)      type-FIXNUM)
  442.     ((SPECIAL)     type-SPECIAL)
  443.     ((PAIR)        type-PAIR)
  444.     ((SUBTYPED)    type-SUBTYPED)
  445.     ((PROCEDURE)   type-PROCEDURE)
  446.     (else
  447.      (compiler-internal-error
  448.        "obj-type-tag, unknown object 'obj'" obj))))
  449.  
  450. (define (obj-encoding obj)
  451.   (case (obj-type obj)
  452.     ((FIXNUM)
  453.      (make-encoding obj type-FIXNUM))
  454.     ((SPECIAL)
  455.      (make-encoding
  456.        (cond ((false-object? obj) data-FALSE)
  457.              ((undef-object? obj) data-UNDEF)
  458.              ((eq? obj #t)        data-TRUE)
  459.              ((null? obj)         data-NULL)
  460.              ((char? obj)         (character-encoding obj))
  461.              (else
  462.               (compiler-internal-error
  463.                 "obj-encoding, unknown SPECIAL object 'obj'" obj)))
  464.        type-SPECIAL))
  465.     (else
  466.      #f)))
  467.  
  468. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  469.  
  470. (define bits-FALSE   (make-encoding data-FALSE   type-SPECIAL))
  471. (define bits-NULL    (make-encoding data-NULL    type-SPECIAL))
  472. (define bits-TRUE    (make-encoding data-TRUE    type-SPECIAL))
  473. (define bits-UNASS   (make-encoding data-UNASS   type-SPECIAL))
  474. (define bits-UNBOUND (make-encoding data-UNBOUND type-SPECIAL))
  475.  
  476.  
  477. ;------------------------------------------------------------------------------
  478. ;
  479. ; M680x0 assembler:
  480. ; ----------------
  481.  
  482. (define (asm.begin!)
  483.   (set! asm-code-queue (queue-empty))
  484.   (set! asm-const-queue (queue-empty))
  485.   '())
  486.  
  487. (define (asm.end! debug-info)
  488.   (asm-assemble! debug-info)
  489.   (set! asm-code-queue '())
  490.   (set! asm-const-queue '())
  491.   '())
  492.  
  493. (define asm-code-queue '())
  494. (define asm-const-queue '())
  495.  
  496. (define (asm-word x)
  497.   (queue-put! asm-code-queue (modulo x #x10000)))
  498.  
  499. (define (asm-long x)
  500.   (asm-word (upper-16bits x))
  501.   (asm-word x))
  502.  
  503. (define (asm-label lbl label-descr)
  504.   (queue-put! asm-code-queue (cons 'LABEL (cons lbl label-descr))))
  505.  
  506. (define (asm-comment x)
  507.   (queue-put! asm-code-queue (cons 'COMMENT x)))
  508.  
  509. (define (asm-align n offset)
  510.   (queue-put! asm-code-queue (cons 'ALIGN (cons n offset))))
  511.  
  512. (define (asm-ref-glob glob)
  513.   (queue-put! asm-code-queue (cons 'REF-GLOB (symbol->string (glob-name glob)))))
  514.  
  515. (define (asm-set-glob glob)
  516.   (queue-put! asm-code-queue (cons 'SET-GLOB (symbol->string (glob-name glob)))))
  517.  
  518. (define (asm-ref-glob-jump glob)
  519.   (queue-put! asm-code-queue (cons 'REF-GLOB-JUMP (symbol->string (glob-name glob)))))
  520.  
  521. (define (asm-proc-ref num offset)
  522.   (queue-put! asm-code-queue
  523.     (cons 'PROC-REF (cons num offset))))
  524.  
  525. (define (asm-prim-ref proc offset)
  526.   (queue-put! asm-code-queue
  527.     (cons 'PRIM-REF (cons (proc-obj-name proc) offset))))
  528.  
  529. (define (asm-M68020-proc)
  530.   (queue-put! asm-code-queue '(M68020-PROC)))
  531.  
  532. (define (asm-M68881-proc)
  533.   (queue-put! asm-code-queue '(M68881-PROC)))
  534.  
  535. (define (asm-stat x)
  536.   (queue-put! asm-code-queue (cons 'STAT x)))
  537.  
  538. (define (asm-brel type lbl)
  539.   (queue-put! asm-code-queue (cons 'BRAB (cons type lbl))))
  540.  
  541. (define (asm-wrel lbl offs)
  542.   (queue-put! asm-code-queue (cons 'WREL (cons lbl offs))))
  543.  
  544. (define (asm-lrel lbl offs n)
  545.   (queue-put! asm-code-queue (cons 'LREL (cons lbl (cons offs n)))))
  546.  
  547.  
  548. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  549.  
  550. (define (asm-assemble! debug-info)
  551.  
  552.   (define header-offset 2)     ; header length before code starts
  553.   (define ref-glob-len 2)      ; length of code for a ref-glob
  554.   (define set-glob-len 10)     ; length of code for a set-glob
  555.   (define ref-glob-jump-len 2) ; length of code for a ref-glob-jump
  556.   (define proc-ref-len 4)      ; length of code for a proc-ref
  557.   (define prim-ref-len 4)      ; length of code for a prim-ref
  558.   (define stat-len 4)          ; length of code for a stat
  559.  
  560.   (define (padding loc n offset)
  561.     (modulo (- offset loc) n))
  562.  
  563.   (queue-put! asm-const-queue debug-info)
  564.  
  565.   (asm-align 4 0)
  566.   (emit-label const-lbl)
  567.  
  568.   (let ((code-list (queue->list asm-code-queue))
  569.         (const-list (queue->list asm-const-queue)))
  570.  
  571.     (let* ((fix-list
  572.              (let loop ((l code-list) (len header-offset) (x '()))
  573.                (if (null? l)
  574.                  (reverse x)
  575.                  (let ((part (car l)) (rest (cdr l)))
  576.                    (if (pair? part)
  577.                      (case (car part)
  578.                        ((LABEL ALIGN BRAB) (loop rest 0 (cons (cons len part) x)))
  579.                        ((WREL)             (loop rest (+ len 2) x))
  580.                        ((LREL)             (loop rest (+ len 4) x))
  581.                        ((REF-GLOB)         (loop rest (+ len ref-glob-len) x))
  582.                        ((SET-GLOB)         (loop rest (+ len set-glob-len) x))
  583.                        ((REF-GLOB-JUMP)    (loop rest (+ len ref-glob-jump-len) x))
  584.                        ((PROC-REF)         (loop rest (+ len proc-ref-len) x))
  585.                        ((PRIM-REF)         (loop rest (+ len prim-ref-len) x))
  586.                        ((STAT)             (loop rest (+ len stat-len) x))
  587.                        ((COMMENT M68020-PROC M68881-PROC)
  588.                                            (loop rest len x))
  589.                        (else
  590.                         (compiler-internal-error
  591.                           "asm-assemble!, unknown code list element" part)))
  592.                      (loop rest (+ len 2) x))))))
  593.            (lbl-list
  594.              (let loop ((l fix-list) (x '()))
  595.                (if (null? l)
  596.                  x
  597.                  (let ((part (cdar l)) (rest (cdr l)))
  598.                    (if (eq? (car part) 'LABEL)
  599.                       (loop rest (cons (cons (cadr part) part) x))
  600.                       (loop rest x)))))))
  601.  
  602.       (define (replace-lbl-refs-by-pointer-to-label)
  603.         (let loop ((l code-list))
  604.           (if (not (null? l))
  605.             (let ((part (car l)) (rest (cdr l)))
  606.               (if (pair? part)
  607.                 (case (car part)
  608.                   ((BRAB)
  609.                    (set-cdr! (cdr part) (cdr (assq (cddr part) lbl-list))))
  610.                   ((WREL)
  611.                    (set-car! (cdr part) (cdr (assq (cadr part) lbl-list))))
  612.                   ((LREL)
  613.                    (set-car! (cdr part) (cdr (assq (cadr part) lbl-list))))))
  614.               (loop rest)))))
  615.  
  616.       (define (assign-loc-to-labels)
  617.         (let loop ((l fix-list) (loc 0))
  618.           (if (not (null? l))
  619.             (let* ((first (car l))
  620.                    (rest (cdr l))
  621.                    (len (car first))
  622.                    (cur-loc (+ loc len))
  623.                    (part (cdr first)))
  624.               (case (car part)
  625.                 ((LABEL)
  626.                  (if (cddr part)
  627.                    (vector-set! (cddr part) 0
  628.                      (quotient (- cur-loc header-offset) 8)))
  629.                  (set-car! (cdr part) cur-loc)
  630.                  (loop rest cur-loc))
  631.                 ((ALIGN)
  632.                  (loop rest (+ cur-loc (padding cur-loc (cadr part) (cddr part)))))
  633.                 ((BRAB)
  634.                  (loop rest (+ cur-loc 2)))
  635.                 ((BRAW)
  636.                  (loop rest (+ cur-loc 4)))
  637.                 (else
  638.                  (compiler-internal-error
  639.                    "assign-loc-to-labels, unknown code list element" part)))))))
  640.  
  641.       (define (branch-tensioning-pass)
  642.  
  643.         (assign-loc-to-labels)
  644.  
  645.         (let loop ((changed? #f) (l fix-list) (loc 0))
  646.           (if (null? l)
  647.             (if changed? (branch-tensioning-pass)) ; do again if anything changed
  648.             (let* ((first (car l))
  649.                    (rest (cdr l))
  650.                    (len (car first))
  651.                    (cur-loc (+ loc len))
  652.                    (part (cdr first)))
  653.               (case (car part)
  654.                 ((LABEL)
  655.                  (loop changed? rest cur-loc))
  656.                 ((ALIGN)
  657.                  (loop changed? rest (+ cur-loc (padding cur-loc (cadr part) (cddr part)))))
  658.                 ((BRAB)
  659.                  (let ((dist (- (cadr (cddr part)) (+ cur-loc 2))))
  660.                    (if (or (< dist -128) (> dist 127) (= dist 0))
  661.                      (begin
  662.                        (set-car! part 'BRAW) ; BRAB -> BRAW if branch too far
  663.                        (loop #t rest (+ cur-loc 2)))
  664.                      (loop changed? rest (+ cur-loc 2)))))
  665.                 ((BRAW)
  666.                  (loop changed? rest (+ cur-loc 4)))
  667.                 (else
  668.                  (compiler-internal-error
  669.                    "branch-tensioning-pass, unknown code list element" part)))))))
  670.  
  671.       (define (write-block start-loc end-loc start end)
  672.         (if (> end-loc start-loc)
  673.           (ofile-word (quotient (- end-loc start-loc) 2)))
  674.         (let loop ((loc start-loc) (l start))
  675.           (if (not (eq? l end))
  676.             (let ((part (car l)) (rest (cdr l)))
  677.               (if (pair? part)
  678.  
  679.                 (case (car part)
  680.  
  681.                   ((LABEL)
  682.                    (loop loc rest))
  683.  
  684.                   ((ALIGN)
  685.                    (let ((n (padding loc (cadr part) (cddr part))))
  686.                      (let pad ((i 0))
  687.                        (if (< i n)
  688.                          (begin
  689.                            (ofile-word 0)
  690.                            (pad (+ i 2)))
  691.                          (loop (+ loc n) rest)))))
  692.  
  693.                   ((BRAB)
  694.                    (let ((dist (- (cadr (cddr part)) (+ loc 2))))
  695.                      (ofile-word (+ (cadr part) (modulo dist 256)))
  696.                      (loop (+ loc 2) rest)))
  697.  
  698.                   ((BRAW)
  699.                    (let ((dist (- (cadr (cddr part)) (+ loc 2))))
  700.                      (ofile-word (cadr part))
  701.                      (ofile-word (modulo dist #x10000))
  702.                      (loop (+ loc 4) rest)))
  703.  
  704.                   ((WREL)
  705.                    (let ((dist (+ (- (cadr (cadr part)) loc) (cddr part))))
  706.                      (ofile-word (modulo dist #x10000))
  707.                      (loop (+ loc 2) rest)))
  708.  
  709.                   ((LREL)
  710.                    (let ((dist (+ (- (cadr (cadr part)) loc) (caddr part))))
  711.                      (ofile-long (+ (* dist #x10000) (cdddr part)))
  712.                      (loop (+ loc 4) rest)))
  713.  
  714.                   ((COMMENT)
  715.                    (let ((x (cdr part)))
  716.                      (if (pair? x)
  717.                        (ofile-comment x)
  718.                        (ofile-pvm-instr x))
  719.                      (loop loc rest))))
  720.  
  721.                 (begin
  722.                   (ofile-word part)
  723.                   (loop (+ loc 2) rest)))))))
  724.       
  725.       (define (write-code)
  726.  
  727.         (let ((proc-len (+ (cadr (cdr (assq const-lbl lbl-list)))
  728.                            (* (length const-list) 4))))
  729.           (if (>= proc-len #x8000)
  730.             (compiler-limitation-error
  731.               "procedure is too big (32K bytes limit per procedure)"))
  732.           (ofile-word (+ #x8000 proc-len)))
  733.  
  734.         (let loop1 ((start code-list)
  735.                     (start-loc header-offset))
  736.           (let loop2 ((end start)
  737.                       (loc start-loc))
  738.             (if (null? end)
  739.               (write-block start-loc loc start end)
  740.               (let ((part (car end)) (rest (cdr end)))
  741.                 (if (pair? part)
  742.  
  743.                   (case (car part)
  744.                     ((LABEL COMMENT) (loop2 rest loc))
  745.                     ((ALIGN)         (loop2 rest (+ loc (padding loc (cadr part) (cddr part)))))
  746.                     ((BRAB WREL)     (loop2 rest (+ loc 2)))
  747.                     ((BRAW)          (loop2 rest (+ loc 4)))
  748.                     ((LREL)          (loop2 rest (+ loc 4)))
  749.                     (else
  750.                      (write-block start-loc loc start end)
  751.                      (case (car part)
  752.                        ((REF-GLOB)
  753.                         (ofile-wsym global-var-ref-tag (cdr part))
  754.                         (loop1 rest (+ loc ref-glob-len)))
  755.                        ((SET-GLOB)
  756.                         (ofile-wsym global-var-set-tag (cdr part))
  757.                         (loop1 rest (+ loc set-glob-len)))
  758.                        ((REF-GLOB-JUMP)
  759.                         (ofile-wsym global-var-ref-jump-tag (cdr part))
  760.                         (loop1 rest (+ loc ref-glob-jump-len)))
  761.                        ((PROC-REF)
  762.                         (ofile-word (+ local-proc-ref-tag (cadr part)))
  763.                         (ofile-word (cddr part))
  764.                         (loop1 rest (+ loc proc-ref-len)))
  765.                        ((PRIM-REF)
  766.                         (ofile-wsym prim-proc-ref-tag (cadr part))
  767.                         (ofile-word (cddr part))
  768.                         (loop1 rest (+ loc prim-ref-len)))
  769.                        ((M68020-PROC)
  770.                         (ofile-word M68020-proc-code-tag)
  771.                         (loop1 rest loc))
  772.                        ((M68881-PROC)
  773.                         (ofile-word M68881-proc-code-tag)
  774.                         (loop1 rest loc))
  775.                        ((STAT)
  776.                         (ofile-word stat-tag)
  777.                         (ofile-stat (cdr part))
  778.                         (loop1 rest (+ loc stat-len))))))
  779.  
  780.                   (loop2 rest (+ loc 2)))))))
  781.  
  782.         (ofile-word end-of-code-tag)
  783.  
  784.         (for-each ofile-ref const-list)
  785.  
  786.         (ofile-long (obj-encoding (+ (length const-list) 1))))
  787.  
  788.       (replace-lbl-refs-by-pointer-to-label)
  789.  
  790.       (branch-tensioning-pass)
  791.  
  792.       (write-code))))
  793.  
  794. (define const-lbl 0)
  795.  
  796.  
  797. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  798. ;
  799. ; M68000 operands:
  800.  
  801. ; All operands are represented with integers or symbols and can be tested for
  802. ; equality using 'eqv?'.  The representation is similar to the actual bit
  803. ; sequence used by the hardware.  This makes for an efficient
  804. ; 'opnd->mode/reg' procedure.
  805.  
  806. (define (identical-opnd68? opnd1 opnd2) (eqv? opnd1 opnd2))
  807.  
  808. (define (reg68? x) (or (dreg? x) (areg? x)))
  809.  
  810. ; -- data register
  811. (define (make-dreg num) num)
  812. (define (dreg? x) (and (integer? x) (>= x 0) (< x 8)))
  813. (define (dreg-num x) x)
  814.  
  815. ; -- address register
  816. (define (make-areg num) (+ num 8))
  817. (define (areg? x) (and (integer? x) (>= x 8) (< x 16)))
  818. (define (areg-num x) (- x 8))
  819.  
  820. ; -- address register indirect
  821. (define (make-ind areg) (+ areg 8))
  822. (define (ind? x) (and (integer? x) (>= x 16) (< x 24)))
  823. (define (ind-areg x) (- x 8))
  824.  
  825. ; -- address register indirect with postincrement
  826. (define (make-pinc areg) (+ areg 16))
  827. (define (pinc? x) (and (integer? x) (>= x 24) (< x 32)))
  828. (define (pinc-areg x) (- x 16))
  829.  
  830. ; -- address register indirect with predecrement
  831. (define (make-pdec areg) (+ areg 24))
  832. (define (pdec? x) (and (integer? x) (>= x 32) (< x 40)))
  833. (define (pdec-areg x) (- x 24))
  834.  
  835. ; -- address register indirect with displacement
  836. (define (make-disp areg offset) (+ (+ areg 32) (* (modulo offset #x10000) 8)))
  837. (define (disp? x) (and (integer? x) (>= x 40) (< x 524328)))
  838. (define (disp-areg x) (+ (remainder x 8) 8))
  839. (define (disp-offset x) (- (modulo (+ (quotient (- x 40) 8) #x8000) #x10000) #x8000))
  840.  
  841. (define (make-disp* areg offset) ; smarter version of 'make-disp'
  842.   (if (= offset 0) (make-ind areg) (make-disp areg offset)))
  843. (define (disp*? x) (or (ind? x) (disp? x)))
  844. (define (disp*-areg x) (if (ind? x) (ind-areg x) (disp-areg x)))
  845. (define (disp*-offset x) (if (ind? x) 0 (disp-offset x)))
  846.  
  847. ; -- address register indirect with index
  848. (define (make-inx areg ireg offset) (+ (+ areg 524320) (* ireg 8) (* (modulo offset #x100) 128)))
  849. (define (inx? x) (and (integer? x) (>= x 524328) (< x 557096)))
  850. (define (inx-areg x) (+ (remainder (- x 524328) 8) 8))
  851. (define (inx-ireg x) (quotient (remainder (- x 524328) 128) 8))
  852. (define (inx-offset x) (- (modulo (+ (quotient (- x 524328) 128) #x80) #x100) #x80))
  853.  
  854. ; -- M68881 floating point coprocessor register
  855. (define (make-freg num) (+ 557096 num))
  856. (define (freg? x) (and (integer? x) (>= x 557096) (< x 557104)))
  857. (define (freg-num x) (- x 557096))
  858.  
  859. ; -- pc relative
  860. (define (make-pcr lbl offset) (+ 557104 (+ (modulo offset #x10000) (* lbl #x10000))))
  861. (define (pcr? x) (and (integer? x) (>= x 557104)))
  862. (define (pcr-lbl x) (quotient (- x 557104) #x10000))
  863. (define (pcr-offset x) (- (modulo (- x 524336) #x10000) #x8000))
  864.  
  865. ; -- immediate
  866. (define (make-imm val) (if (< val 0) (* val 2) (- -1 (* val 2))))
  867. (define (imm? x) (and (integer? x) (< x 0)))
  868. (define (imm-val x) (if (even? x) (quotient x 2) (- (quotient x 2))))
  869.  
  870. ; -- global variable
  871. (define (make-glob name) name)
  872. (define (glob? x) (symbol? x))
  873. (define (glob-name x) x)
  874.  
  875. ; -- 'frame base relative' stack operand
  876. (define (make-frame-base-rel slot) (make-disp sp-reg slot))
  877. (define (frame-base-rel? x) (and (disp? x) (identical-opnd68? sp-reg (disp-areg x))))
  878. (define (frame-base-rel-slot x) (disp-offset x))
  879.  
  880. ; -- register list
  881. (define (make-reg-list regs) regs)
  882. (define (reg-list? x) (or (pair? x) (null? x)))
  883. (define (reg-list-regs x) x)
  884.  
  885. ; Common operands:
  886.  
  887. (define first-dtemp     0)             ; first data register temporary
  888. (define pvm-reg1        1)             ; first general PVM register
  889. (define intr-timer-reg  (make-dreg 5)) ; countdown timer for interrupts
  890. (define null-reg        (make-dreg 6)) ; register that contains ()
  891. (define placeholder-reg (make-dreg 6)) ; future mask register
  892. (define false-reg       (make-dreg 7)) ; register that contains #f
  893. (define pair-reg        (make-dreg 7)) ; pair mask register
  894.  
  895. (define pvm-reg0       0)             ; return address register
  896. (define first-atemp    1)             ; first address register temporary
  897. (define heap-reg       (make-areg 3)) ; heaplet allocation register
  898. (define ltq-tail-reg   (make-areg 4)) ; pointer to tail of lazy task queue
  899. (define pstate-reg     (make-areg 5)) ; processor state pointer register
  900. (define table-reg      (make-areg 6)) ; global variable and code pointer register
  901. (define sp-reg         (make-areg 7)) ; stack pointer register
  902.  
  903. (define pdec-sp        (make-pdec sp-reg)) ; push
  904. (define pinc-sp        (make-pinc sp-reg)) ; pop
  905.  
  906. (define dtemp1         (make-dreg first-dtemp))
  907. (define atemp1         (make-areg first-atemp))
  908. (define atemp2         (make-areg (+ first-atemp 1)))
  909. (define ftemp1         (make-freg 0))
  910. (define ftemp2         (make-freg 1))
  911.  
  912. (define arg-count-reg  dtemp1)
  913.  
  914. (define (trap-offset n)
  915.   (+ #x8000 (* (- n 32) 8)))
  916.  
  917.  
  918. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  919. ;
  920. ; M68000 instructions:
  921.  
  922. (define (emit-move.l opnd1 opnd2)
  923.   (let ((src (opnd->mode/reg opnd1))
  924.         (dst (opnd->reg/mode opnd2)))
  925.     (asm-word (+ #x2000 (+ dst src)))
  926.     (opnd-ext-rd-long opnd1)
  927.     (opnd-ext-wr-long opnd2)
  928.     (if ofile-asm?
  929.       (emit-asm "movl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))))
  930.  
  931. (define (emit-move.w opnd1 opnd2)
  932.   (let ((src (opnd->mode/reg opnd1))
  933.         (dst (opnd->reg/mode opnd2)))
  934.     (asm-word (+ #x3000 (+ dst src)))
  935.     (opnd-ext-rd-word opnd1)
  936.     (opnd-ext-wr-word opnd2)
  937.     (if ofile-asm?
  938.       (emit-asm "movw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))))
  939.  
  940. (define (emit-move.b opnd1 opnd2)
  941.   (let ((src (opnd->mode/reg opnd1))
  942.         (dst (opnd->reg/mode opnd2)))
  943.     (asm-word (+ #x1000 (+ dst src)))
  944.     (opnd-ext-rd-word opnd1)
  945.     (opnd-ext-wr-word opnd2)
  946.     (if ofile-asm?
  947.       (emit-asm "movb" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))))
  948.  
  949. (define (emit-moveq n opnd)
  950.   (asm-word (+ #x7000 (+ (* (dreg-num opnd) 512) (modulo n 256))))
  951.   (if ofile-asm?
  952.     (emit-asm "moveq" ofile-tab "#" n "," (opnd-str opnd))))
  953.  
  954. (define (emit-movem.l opnd1 opnd2)
  955.  
  956.   (define (reg-mask reg-list flip-bits?)
  957.     (let loop ((i 15) (bit #x8000) (mask 0))
  958.       (if (>= i 0)
  959.         (loop (- i 1)
  960.               (quotient bit 2)
  961.               (if (memq i reg-list)
  962.                 (+ mask (if flip-bits? (quotient #x8000 bit) bit))
  963.                 mask))
  964.         mask)))
  965.  
  966.   (define (movem op reg-list opnd)
  967.     (asm-word (+ op (opnd->mode/reg opnd)))
  968.     (asm-word (reg-mask reg-list (pdec? opnd))))
  969.  
  970.   (if (reg-list? opnd1)
  971.     (begin
  972.       (movem #x48c0 opnd1 opnd2)
  973.       (opnd-ext-wr-long opnd2))
  974.     (begin
  975.       (movem #x4cc0 opnd2 opnd1)
  976.       (opnd-ext-rd-long opnd1)))
  977.   (if ofile-asm?
  978.     (emit-asm "moveml" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  979.  
  980. (define (emit-exg opnd1 opnd2)
  981.   (define (exg r1 r2)
  982.     (let ((mode (if (dreg? r2) #xc140 (if (dreg? r1) #xc188 #xc148)))
  983.           (num1 (if (dreg? r1) (dreg-num r1) (areg-num r1)))
  984.           (num2 (if (dreg? r2) (dreg-num r2) (areg-num r2))))
  985.       (asm-word (+ mode (+ (* num1 512) num2)))))
  986.   (if (dreg? opnd2) (exg opnd2 opnd1) (exg opnd1 opnd2))
  987.   (if ofile-asm?
  988.     (emit-asm "exg" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  989.  
  990. (define (emit-eor.l opnd1 opnd2)
  991.   (cond ((imm? opnd1)
  992.          (asm-word (+ #x0a80 (opnd->mode/reg opnd2)))
  993.          (opnd-ext-rd-long opnd1)
  994.          (opnd-ext-wr-long opnd2))
  995.         (else
  996.          (asm-word (+ #xb180 (+ (* (dreg-num opnd1) 512) (opnd->mode/reg opnd2))))
  997.          (opnd-ext-wr-long opnd2)))
  998.   (if ofile-asm?
  999.     (emit-asm "eorl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1000.  
  1001. (define (emit-and.l opnd1 opnd2)
  1002.   (cond ((imm? opnd1)
  1003.          (asm-word (+ #x0280 (opnd->mode/reg opnd2)))
  1004.          (opnd-ext-rd-long opnd1)
  1005.          (opnd-ext-wr-long opnd2))
  1006.         (else
  1007.          (let ((mode (if (dreg? opnd2) #xc080 #xc180))
  1008.                (reg (if (dreg? opnd2) (dreg-num opnd2) (dreg-num opnd1)))
  1009.                (other (if (dreg? opnd2) opnd1 opnd2)))
  1010.            (asm-word (+ mode (+ (* reg 512) (opnd->mode/reg other))))
  1011.            (if (dreg? opnd2)
  1012.              (opnd-ext-rd-long other)
  1013.              (opnd-ext-wr-long other)))))
  1014.   (if ofile-asm?
  1015.     (emit-asm "andl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1016.  
  1017. (define (emit-and.w opnd1 opnd2)
  1018.   (cond ((imm? opnd1)
  1019.          (asm-word (+ #x0240 (opnd->mode/reg opnd2)))
  1020.          (opnd-ext-rd-word opnd1)
  1021.          (opnd-ext-wr-word opnd2))
  1022.         (else
  1023.          (let ((mode (if (dreg? opnd2) #xc040 #xc140))
  1024.                (reg (if (dreg? opnd2) (dreg-num opnd2) (dreg-num opnd1)))
  1025.                (other (if (dreg? opnd2) opnd1 opnd2)))
  1026.            (asm-word (+ mode (+ (* reg 512) (opnd->mode/reg other))))
  1027.            (if (dreg? opnd2)
  1028.              (opnd-ext-rd-word other)
  1029.              (opnd-ext-wr-word other)))))
  1030.   (if ofile-asm?
  1031.     (emit-asm "andw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1032.  
  1033. (define (emit-or.l opnd1 opnd2)
  1034.   (cond ((imm? opnd1)
  1035.          (asm-word (+ #x0080 (opnd->mode/reg opnd2)))
  1036.          (opnd-ext-rd-long opnd1)
  1037.          (opnd-ext-wr-long opnd2))
  1038.         (else
  1039.          (let ((mode (if (dreg? opnd2) #x8080 #x8180))
  1040.                (reg (if (dreg? opnd2) (dreg-num opnd2) (dreg-num opnd1)))
  1041.                (other (if (dreg? opnd2) opnd1 opnd2)))
  1042.            (asm-word (+ mode (+ (* reg 512) (opnd->mode/reg other))))
  1043.            (if (dreg? opnd2)
  1044.              (opnd-ext-rd-long other)
  1045.              (opnd-ext-wr-long other)))))
  1046.   (if ofile-asm?
  1047.     (emit-asm "orl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1048.  
  1049. (define (emit-addq.l n opnd)
  1050.   (let ((m (if (= n 8) 0 n)))
  1051.     (asm-word (+ #x5080 (* m 512) (opnd->mode/reg opnd)))
  1052.     (opnd-ext-wr-long opnd)
  1053.     (if ofile-asm?
  1054.       (emit-asm "addql" ofile-tab "#" n "," (opnd-str opnd)))))
  1055.  
  1056. (define (emit-addq.w n opnd)
  1057.   (let ((m (if (= n 8) 0 n)))
  1058.     (asm-word (+ #x5040 (* m 512) (opnd->mode/reg opnd)))
  1059.     (opnd-ext-wr-word opnd)
  1060.     (if ofile-asm?
  1061.       (emit-asm "addqw" ofile-tab "#" n "," (opnd-str opnd)))))
  1062.  
  1063. (define (emit-add.l opnd1 opnd2)
  1064.   (cond ((areg? opnd2)
  1065.          (asm-word (+ #xd1c0 (+ (* (areg-num opnd2) 512) (opnd->mode/reg opnd1))))
  1066.          (opnd-ext-rd-long opnd1))
  1067.         ((imm? opnd1)
  1068.          (asm-word (+ #x0680 (opnd->mode/reg opnd2)))
  1069.          (opnd-ext-rd-long opnd1)
  1070.          (opnd-ext-wr-long opnd2))
  1071.         (else
  1072.          (let ((mode (if (dreg? opnd2) #xd080 #xd180))
  1073.                (reg (if (dreg? opnd2) (dreg-num opnd2) (dreg-num opnd1)))
  1074.                (other (if (dreg? opnd2) opnd1 opnd2)))
  1075.            (asm-word (+ mode (+ (* reg 512) (opnd->mode/reg other))))
  1076.            (if (dreg? opnd2)
  1077.              (opnd-ext-rd-long other)
  1078.              (opnd-ext-wr-long other)))))
  1079.   (if ofile-asm?
  1080.     (emit-asm "addl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1081.  
  1082. (define (emit-add.w opnd1 opnd2)
  1083.   (cond ((areg? opnd2)
  1084.          (asm-word (+ #xd0c0 (+ (* (areg-num opnd2) 512) (opnd->mode/reg opnd1))))
  1085.          (opnd-ext-rd-word opnd1))
  1086.         ((imm? opnd1)
  1087.          (asm-word (+ #x0640 (opnd->mode/reg opnd2)))
  1088.          (opnd-ext-rd-word opnd1)
  1089.          (opnd-ext-rd-word opnd2))
  1090.         (else
  1091.          (let ((mode (if (dreg? opnd2) #xd040 #xd140))
  1092.                (reg (if (dreg? opnd2) (dreg-num opnd2) (dreg-num opnd1)))
  1093.                (other (if (dreg? opnd2) opnd1 opnd2)))
  1094.            (asm-word (+ mode (+ (* reg 512) (opnd->mode/reg other))))
  1095.            (if (dreg? opnd2)
  1096.              (opnd-ext-rd-word other)
  1097.              (opnd-ext-wr-word other)))))
  1098.   (if ofile-asm?
  1099.     (emit-asm "addw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1100.  
  1101. (define (emit-addx.w opnd1 opnd2)
  1102.   (if (dreg? opnd1)
  1103.     (asm-word (+ #xd140 (+ (* (dreg-num opnd2) 512) (dreg-num opnd1))))
  1104.     (asm-word (+ #xd148 (+ (* (areg-num (pdec-areg opnd2)) 512) (areg-num (pdec-areg opnd1))))))
  1105.   (if ofile-asm?
  1106.     (emit-asm "addxw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1107.  
  1108. (define (emit-subq.l n opnd)
  1109.   (let ((m (if (= n 8) 0 n)))
  1110.     (asm-word (+ #x5180 (* m 512) (opnd->mode/reg opnd)))
  1111.     (opnd-ext-wr-long opnd)
  1112.     (if ofile-asm?
  1113.       (emit-asm "subql" ofile-tab "#" n "," (opnd-str opnd)))))
  1114.  
  1115. (define (emit-subq.w n opnd)
  1116.   (let ((m (if (= n 8) 0 n)))
  1117.     (asm-word (+ #x5140 (* m 512) (opnd->mode/reg opnd)))
  1118.     (opnd-ext-wr-word opnd)
  1119.     (if ofile-asm?
  1120.       (emit-asm "subqw" ofile-tab "#" n "," (opnd-str opnd)))))
  1121.  
  1122. (define (emit-sub.l opnd1 opnd2)
  1123.   (cond ((areg? opnd2)
  1124.          (asm-word (+ #x91c0 (+ (* (areg-num opnd2) 512) (opnd->mode/reg opnd1))))
  1125.          (opnd-ext-rd-long opnd1))
  1126.         ((imm? opnd1)
  1127.          (asm-word (+ #x0480 (opnd->mode/reg opnd2)))
  1128.          (opnd-ext-rd-long opnd1)
  1129.          (opnd-ext-rd-long opnd2))
  1130.         (else
  1131.          (let ((mode (if (dreg? opnd2) #x9080 #x9180))
  1132.                (reg (if (dreg? opnd2) (dreg-num opnd2) (dreg-num opnd1)))
  1133.                (other (if (dreg? opnd2) opnd1 opnd2)))
  1134.            (asm-word (+ mode (+ (* reg 512) (opnd->mode/reg other))))
  1135.            (if (dreg? opnd2)
  1136.              (opnd-ext-rd-long other)
  1137.              (opnd-ext-wr-long other)))))
  1138.   (if ofile-asm?
  1139.     (emit-asm "subl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1140.  
  1141. (define (emit-asl.l opnd1 opnd2)
  1142.   (if (dreg? opnd1)
  1143.     (asm-word (+ #xe1a0 (+ (* (dreg-num opnd1) 512) (dreg-num opnd2))))
  1144.     (let ((n (imm-val opnd1)))
  1145.       (asm-word (+ #xe180 (+ (* (if (= n 8) 0 n) 512) (dreg-num opnd2))))))
  1146.   (if ofile-asm?
  1147.     (emit-asm "asll" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1148.  
  1149. (define (emit-asl.w opnd1 opnd2)
  1150.   (if (dreg? opnd1)
  1151.     (asm-word (+ #xe160 (+ (* (dreg-num opnd1) 512) (dreg-num opnd2))))
  1152.     (let ((n (imm-val opnd1)))
  1153.       (asm-word (+ #xe140 (+ (* (if (= n 8) 0 n) 512) (dreg-num opnd2))))))
  1154.   (if ofile-asm?
  1155.     (emit-asm "aslw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1156.  
  1157. (define (emit-asr.l opnd1 opnd2)
  1158.   (if (dreg? opnd1)
  1159.     (asm-word (+ #xe0a0 (+ (* (dreg-num opnd1) 512) (dreg-num opnd2))))
  1160.     (let ((n (imm-val opnd1)))
  1161.       (asm-word (+ #xe080 (+ (* (if (= n 8) 0 n) 512) (dreg-num opnd2))))))
  1162.   (if ofile-asm?
  1163.     (emit-asm "asrl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1164.  
  1165. (define (emit-asr.w opnd1 opnd2)
  1166.   (if (dreg? opnd1)
  1167.     (asm-word (+ #xe060 (+ (* (dreg-num opnd1) 512) (dreg-num opnd2))))
  1168.     (let ((n (imm-val opnd1)))
  1169.       (asm-word (+ #xe040 (+ (* (if (= n 8) 0 n) 512) (dreg-num opnd2))))))
  1170.   (if ofile-asm?
  1171.     (emit-asm "asrw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1172.  
  1173. (define (emit-lsl.l opnd1 opnd2)
  1174.   (if (dreg? opnd1)
  1175.     (asm-word (+ #xe1a8 (+ (* (dreg-num opnd1) 512) (dreg-num opnd2))))
  1176.     (let ((n (imm-val opnd1)))
  1177.       (asm-word (+ #xe188 (+ (* (if (= n 8) 0 n) 512) (dreg-num opnd2))))))
  1178.   (if ofile-asm?
  1179.     (emit-asm "lsll" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1180.  
  1181. (define (emit-lsr.l opnd1 opnd2)
  1182.   (if (dreg? opnd1)
  1183.     (asm-word (+ #xe0a8 (+ (* (dreg-num opnd1) 512) (dreg-num opnd2))))
  1184.     (let ((n (imm-val opnd1)))
  1185.       (asm-word (+ #xe088 (+ (* (if (= n 8) 0 n) 512) (dreg-num opnd2))))))
  1186.   (if ofile-asm?
  1187.     (emit-asm "lsrl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1188.  
  1189. (define (emit-lsr.w opnd1 opnd2)
  1190.   (if (dreg? opnd1)
  1191.     (asm-word (+ #xe068 (+ (* (dreg-num opnd1) 512) (dreg-num opnd2))))
  1192.     (let ((n (imm-val opnd1)))
  1193.       (asm-word (+ #xe048 (+ (* (if (= n 8) 0 n) 512) (dreg-num opnd2))))))
  1194.   (if ofile-asm?
  1195.     (emit-asm "lsrw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1196.  
  1197. (define (emit-clr.l opnd)
  1198.   (asm-word (+ #x4280 (opnd->mode/reg opnd)))
  1199.   (opnd-ext-wr-long opnd)
  1200.   (if ofile-asm?
  1201.     (emit-asm "clrl" ofile-tab (opnd-str opnd))))
  1202.  
  1203. (define (emit-neg.l opnd)
  1204.   (asm-word (+ #x4480 (opnd->mode/reg opnd)))
  1205.   (opnd-ext-wr-long opnd)
  1206.   (if ofile-asm?
  1207.     (emit-asm "negl" ofile-tab (opnd-str opnd))))
  1208.  
  1209. (define (emit-not.l opnd)
  1210.   (asm-word (+ #x4680 (opnd->mode/reg opnd)))
  1211.   (opnd-ext-wr-long opnd)
  1212.   (if ofile-asm?
  1213.     (emit-asm "notl" ofile-tab (opnd-str opnd))))
  1214.  
  1215. (define (emit-ext.l opnd)
  1216.   (asm-word (+ #x48c0 (dreg-num opnd)))
  1217.   (if ofile-asm?
  1218.     (emit-asm "extl" ofile-tab (opnd-str opnd))))
  1219.  
  1220. (define (emit-ext.w opnd)
  1221.   (asm-word (+ #x4880 (dreg-num opnd)))
  1222.   (if ofile-asm?
  1223.     (emit-asm "extw" ofile-tab (opnd-str opnd))))
  1224.  
  1225. (define (emit-swap opnd)
  1226.   (asm-word (+ #x4840 (dreg-num opnd)))
  1227.   (if ofile-asm?
  1228.     (emit-asm "swap" ofile-tab (opnd-str opnd))))
  1229.  
  1230. (define (emit-cmp.l opnd1 opnd2)
  1231.   (cond ((areg? opnd2)
  1232.          (asm-word (+ #xb1c0 (+ (* (areg-num opnd2) 512) (opnd->mode/reg opnd1))))
  1233.          (opnd-ext-rd-long opnd1))
  1234.         ((imm? opnd1)
  1235.          (asm-word (+ #x0c80 (opnd->mode/reg opnd2)))
  1236.          (opnd-ext-rd-long opnd1)
  1237.          (opnd-ext-rd-long opnd2))
  1238.         (else
  1239.          (asm-word (+ #xb080 (+ (* (dreg-num opnd2) 512) (opnd->mode/reg opnd1))))
  1240.          (opnd-ext-rd-long opnd1)))
  1241.   (if ofile-asm?
  1242.     (emit-asm "cmpl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1243.  
  1244. (define (emit-cmp.w opnd1 opnd2)
  1245.   (cond ((areg? opnd2)
  1246.          (asm-word (+ #xb0c0 (+ (* (areg-num opnd2) 512) (opnd->mode/reg opnd1))))
  1247.          (opnd-ext-rd-word opnd1))
  1248.         ((imm? opnd1)
  1249.          (asm-word (+ #x0c40 (opnd->mode/reg opnd2)))
  1250.          (opnd-ext-rd-word opnd1)
  1251.          (opnd-ext-rd-word opnd2))
  1252.         (else
  1253.          (asm-word (+ #xb040 (+ (* (dreg-num opnd2) 512) (opnd->mode/reg opnd1))))
  1254.          (opnd-ext-rd-word opnd1)))
  1255.   (if ofile-asm?
  1256.     (emit-asm "cmpw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1257.  
  1258. (define (emit-cmp.b opnd1 opnd2)
  1259.   (cond ((imm? opnd1)
  1260.          (asm-word (+ #x0c00 (opnd->mode/reg opnd2)))
  1261.          (opnd-ext-rd-word opnd1)
  1262.          (opnd-ext-rd-word opnd2))
  1263.         (else
  1264.          (asm-word (+ #xb000 (+ (* (dreg-num opnd2) 512) (opnd->mode/reg opnd1))))
  1265.          (opnd-ext-rd-word opnd1)))
  1266.   (if ofile-asm?
  1267.     (emit-asm "cmpb" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1268.  
  1269. (define (emit-tst.l opnd)
  1270.   (asm-word (+ #x4a80 (opnd->mode/reg opnd)))
  1271.   (opnd-ext-rd-long opnd)
  1272.   (if ofile-asm?
  1273.     (emit-asm "tstl" ofile-tab (opnd-str opnd))))
  1274.  
  1275. (define (emit-tst.w opnd)
  1276.   (asm-word (+ #x4a40 (opnd->mode/reg opnd)))
  1277.   (opnd-ext-rd-word opnd)
  1278.   (if ofile-asm?
  1279.     (emit-asm "tstw" ofile-tab (opnd-str opnd))))
  1280.  
  1281. (define (emit-lea opnd areg)
  1282.   (asm-word (+ #x41c0 (+ (* (areg-num areg) 512) (opnd->mode/reg opnd))))
  1283.   (opnd-ext-rd-long opnd)
  1284.   (if ofile-asm?
  1285.     (emit-asm "lea" ofile-tab (opnd-str opnd) "," (opnd-str areg))))
  1286.  
  1287. (define (emit-unlk areg)
  1288.   (asm-word (+ #x4e58 (areg-num areg)))
  1289.   (if ofile-asm?
  1290.     (emit-asm "unlk" ofile-tab (opnd-str areg))))
  1291.  
  1292. (define (emit-tas opnd)
  1293.   (asm-word (+ #x4ac0 (opnd->mode/reg opnd)))
  1294.   (opnd-ext-wr-long opnd)
  1295.   (if ofile-asm?
  1296.     (emit-asm "tas" ofile-tab (opnd-str opnd))))
  1297.  
  1298. (define (emit-lea* n areg)
  1299.   (asm-word (+ #x41f8 (* (areg-num areg) 512)))
  1300.   (asm-word n)
  1301.   (if ofile-asm?
  1302.     (emit-asm "lea" ofile-tab n "," (opnd-str areg))))
  1303.  
  1304. (define (emit-move-proc num opnd)
  1305.   (let ((dst (opnd->reg/mode opnd)))
  1306.     (asm-word (+ #x2000 (+ dst 60)))
  1307.     (asm-proc-ref num 0)
  1308.     (opnd-ext-wr-long opnd)
  1309.     (if ofile-asm?
  1310.       (emit-asm "MOVE_PROC(" num "," (opnd-str opnd) ")"))))
  1311.  
  1312. (define (emit-move-prim val opnd)
  1313.   (let ((dst (opnd->reg/mode opnd)))
  1314.     (asm-word (+ #x2000 (+ dst 60)))
  1315.     (asm-prim-ref val 0)
  1316.     (opnd-ext-wr-long opnd)
  1317.     (if ofile-asm?
  1318.       (emit-asm "MOVE_PRIM(" (proc-obj-name val) "," (opnd-str opnd) ")"))))
  1319.  
  1320. (define (emit-pea opnd)
  1321.   (asm-word (+ #x4840 (opnd->mode/reg opnd)))
  1322.   (opnd-ext-rd-long opnd)
  1323.   (if ofile-asm?
  1324.     (emit-asm "pea" ofile-tab (opnd-str opnd))))
  1325.  
  1326. (define (emit-pea* n)
  1327.   (asm-word #x4878)
  1328.   (asm-word n)
  1329.   (if ofile-asm?
  1330.     (emit-asm "pea" ofile-tab n)))
  1331.  
  1332. (define (emit-btst opnd1 opnd2)
  1333.   (asm-word (+ #x0100 (+ (* (dreg-num opnd1) 512) (opnd->mode/reg opnd2))))
  1334.   (opnd-ext-rd-word opnd2)
  1335.   (if ofile-asm?
  1336.     (emit-asm "btst" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1337.  
  1338. (define (emit-bra lbl)
  1339.   (asm-brel #x6000 lbl)
  1340.   (if ofile-asm?
  1341.     (emit-asm "bra" ofile-tab "L" lbl)))
  1342.  
  1343. (define (emit-bcc lbl)
  1344.   (asm-brel #x6400 lbl)
  1345.   (if ofile-asm?
  1346.     (emit-asm "bcc" ofile-tab "L" lbl)))
  1347.  
  1348. (define (emit-bcs lbl)
  1349.   (asm-brel #x6500 lbl)
  1350.   (if ofile-asm?
  1351.     (emit-asm "bcs" ofile-tab "L" lbl)))
  1352.  
  1353. (define (emit-bhi lbl)
  1354.   (asm-brel #x6200 lbl)
  1355.   (if ofile-asm?
  1356.     (emit-asm "bhi" ofile-tab "L" lbl)))
  1357.  
  1358. (define (emit-bls lbl)
  1359.   (asm-brel #x6300 lbl)
  1360.   (if ofile-asm?
  1361.     (emit-asm "bls" ofile-tab "L" lbl)))
  1362.  
  1363. (define (emit-bmi lbl)
  1364.   (asm-brel #x6b00 lbl)
  1365.   (if ofile-asm?
  1366.     (emit-asm "bmi" ofile-tab "L" lbl)))
  1367.  
  1368. (define (emit-bpl lbl)
  1369.   (asm-brel #x6a00 lbl)
  1370.   (if ofile-asm?
  1371.     (emit-asm "bpl" ofile-tab "L" lbl)))
  1372.  
  1373. (define (emit-beq lbl)
  1374.   (asm-brel #x6700 lbl)
  1375.   (if ofile-asm?
  1376.     (emit-asm "beq" ofile-tab "L" lbl)))
  1377.  
  1378. (define (emit-bne lbl)
  1379.   (asm-brel #x6600 lbl)
  1380.   (if ofile-asm?
  1381.     (emit-asm "bne" ofile-tab "L" lbl)))
  1382.  
  1383. (define (emit-blt lbl)
  1384.   (asm-brel #x6d00 lbl)
  1385.   (if ofile-asm?
  1386.     (emit-asm "blt" ofile-tab "L" lbl)))
  1387.  
  1388. (define (emit-bgt lbl)
  1389.   (asm-brel #x6e00 lbl)
  1390.   (if ofile-asm?
  1391.     (emit-asm "bgt" ofile-tab "L" lbl)))
  1392.  
  1393. (define (emit-ble lbl)
  1394.   (asm-brel #x6f00 lbl)
  1395.   (if ofile-asm?
  1396.     (emit-asm "ble" ofile-tab "L" lbl)))
  1397.  
  1398. (define (emit-bge lbl)
  1399.   (asm-brel #x6c00 lbl)
  1400.   (if ofile-asm?
  1401.     (emit-asm "bge" ofile-tab "L" lbl)))
  1402.  
  1403. (define (emit-dbra dreg lbl)
  1404.   (asm-word (+ #x51c8 dreg))
  1405.   (asm-wrel lbl 0)
  1406.   (if ofile-asm?
  1407.     (emit-asm "dbra" ofile-tab (opnd-str dreg) ",L" lbl)))
  1408.  
  1409. (define (emit-trap num)
  1410.   (asm-word (+ #x4e40 num))
  1411.   (if ofile-asm?
  1412.     (emit-asm "trap" ofile-tab "#" num)))
  1413.  
  1414. (define (emit-trap1 num args)
  1415.   (asm-word (+ #x4ea8 (areg-num table-reg)))
  1416.   (asm-word (trap-offset num))
  1417.   (let loop ((args args))
  1418.     (if (not (null? args))
  1419.       (begin
  1420.         (asm-word (car args))
  1421.         (loop (cdr args)))))
  1422.   (if ofile-asm?
  1423.     (let ()
  1424.       (define (words l)
  1425.         (if (null? l) (list ")") (cons "," (cons (car l) (words (cdr l))))))
  1426.       (apply emit-asm (cons "TRAP1(" (cons num (words args)))))))
  1427.  
  1428. (define (emit-trap2 num args)
  1429.   (asm-word (+ #x4ea8 (areg-num table-reg)))
  1430.   (asm-word (trap-offset num))
  1431.   (asm-align 8 (modulo (- 4 (* (length args) 2)) 8))
  1432.   (let loop ((args args))
  1433.     (if (not (null? args))
  1434.       (begin
  1435.         (asm-word (car args))
  1436.         (loop (cdr args)))))
  1437.   (if ofile-asm?
  1438.     (let ()
  1439.       (define (words l)
  1440.         (if (null? l) (list ")") (cons "," (cons (car l) (words (cdr l))))))
  1441.       (apply emit-asm (cons "TRAP2(" (cons num (words args)))))))
  1442.  
  1443. (define (emit-trap3 num)
  1444.   (asm-word (+ #x4ee8 (areg-num table-reg)))
  1445.   (asm-word (trap-offset num))
  1446.   (if ofile-asm?
  1447.     (emit-asm "TRAP3(" num ")")))
  1448.  
  1449. (define (emit-rts)
  1450.   (asm-word #x4e75)
  1451.   (if ofile-asm?
  1452.     (emit-asm "rts")))
  1453.  
  1454. (define (emit-nop)
  1455.   (asm-word #x4e71)
  1456.   (if ofile-asm?
  1457.     (emit-asm "nop")))
  1458.  
  1459. (define (emit-jmp opnd)
  1460.   (asm-word (+ #x4ec0 (opnd->mode/reg opnd)))
  1461.   (opnd-ext-rd-long opnd)
  1462.   (if ofile-asm?
  1463.     (emit-asm "jmp" ofile-tab (opnd-str opnd))))
  1464.  
  1465. (define (emit-jmp-glob glob)
  1466.   (asm-word #x226e)
  1467.   (asm-ref-glob-jump glob)
  1468.   (asm-word #x4ed1)
  1469.   (if ofile-asm?
  1470.     (emit-asm "JMP_GLOB(" (glob-name glob) ")")))
  1471.  
  1472. (define (emit-jmp-proc num offset)
  1473.   (asm-word #x4ef9)
  1474.   (asm-proc-ref num offset)
  1475.   (if ofile-asm?
  1476.     (emit-asm "JMP_PROC(" num "," offset ")")))
  1477.  
  1478. (define (emit-jmp-prim val offset)
  1479.   (asm-word #x4ef9)
  1480.   (asm-prim-ref val offset)
  1481.   (if ofile-asm?
  1482.     (emit-asm "JMP_PRIM(" (proc-obj-name val) "," offset ")")))
  1483.  
  1484. (define (emit-jsr opnd)
  1485.   (asm-word (+ #x4e80 (opnd->mode/reg opnd)))
  1486.   (opnd-ext-rd-long opnd)
  1487.   (if ofile-asm?
  1488.     (emit-asm "jsr" ofile-tab (opnd-str opnd))))
  1489.  
  1490. (define (emit-word n)
  1491.   (asm-word n)
  1492.   (if ofile-asm?
  1493.     (emit-asm ".word" ofile-tab n)))
  1494.  
  1495. (define (emit-label lbl)
  1496.   (asm-label lbl #f)
  1497.   (if ofile-asm?
  1498.     (emit-asm* "L" lbl ":")))
  1499.  
  1500. (define (emit-label-subproc lbl parent-lbl label-descr)
  1501.   (asm-align 8 0)
  1502.   (asm-wrel parent-lbl (- #x8000 type-PROCEDURE))
  1503.   (asm-label lbl label-descr)
  1504.   (if ofile-asm?
  1505.     (begin
  1506.       (emit-asm "SUBPROC(L" parent-lbl ")")
  1507.       (emit-asm* "L" lbl ":"))))
  1508.  
  1509. (define (emit-label-return lbl parent-lbl fs link label-descr)
  1510.   (asm-align 8 4)
  1511.   (asm-word (* fs 4))
  1512.   (asm-word (* (- fs link) 4))
  1513.   (asm-wrel parent-lbl (- #x8000 type-PROCEDURE))
  1514.   (asm-label lbl label-descr)
  1515.   (if ofile-asm?
  1516.     (begin
  1517.       (emit-asm "RETURN(L" parent-lbl "," fs "," link ")")
  1518.       (emit-asm* "L" lbl ":"))))
  1519.  
  1520. (define (emit-label-return-lazy lbl parent-lbl fs link label-descr)
  1521.   (asm-align 8 4)
  1522.   (asm-word (+ #x8000 (* fs 4)))
  1523.   (asm-word (* (- fs link) 4))
  1524.   (asm-wrel parent-lbl (- #x8000 type-PROCEDURE))
  1525.   (asm-label lbl label-descr)
  1526.   (if ofile-asm?
  1527.     (begin
  1528.       (emit-asm "RETURN_LAZY(L" parent-lbl "," fs "," link ")")
  1529.       (emit-asm* "L" lbl ":"))))
  1530.  
  1531. (define (emit-lbl-ptr lbl)
  1532.   (asm-wrel lbl 0)
  1533.   (if ofile-asm?
  1534.     (emit-asm "LBL_PTR(L" lbl ")")))
  1535.  
  1536. (define (emit-set-glob glob)
  1537.   (asm-set-glob glob)
  1538.   (if ofile-asm?
  1539.     (emit-asm "SET_GLOB(" (glob-name glob) ")")))
  1540.  
  1541. (define (emit-const obj)
  1542.   (let ((n (pos-in-list obj (queue->list asm-const-queue))))
  1543.     (if n
  1544.       (make-pcr const-lbl (* n 4))
  1545.       (let ((m (length (queue->list asm-const-queue))))
  1546.         (queue-put! asm-const-queue obj)
  1547.         (make-pcr const-lbl (* m 4))))))
  1548.  
  1549. (define (emit-stat stat)
  1550.   (asm-word #x52b9)
  1551.   (asm-stat stat)
  1552.   (if ofile-asm?
  1553.     (emit-asm "STAT(" stat ")")))
  1554.  
  1555. (define (emit-asm . l)
  1556.   (asm-comment (cons ofile-tab l)))
  1557.  
  1558. (define (emit-asm* . l)
  1559.   (asm-comment l))
  1560.  
  1561.  
  1562. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1563. ;
  1564. ; M68020 instructions:
  1565.  
  1566. (define (emit-muls.l opnd1 opnd2)
  1567.   (asm-M68020-proc)
  1568.   (asm-word (+ #x4c00 (opnd->mode/reg opnd1)))
  1569.   (asm-word (+ #x0800 (* (dreg-num opnd2) 4096)))
  1570.   (opnd-ext-rd-long opnd1)
  1571.   (if ofile-asm?
  1572.     (emit-asm "mulsl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1573.  
  1574. (define (emit-divsl.l opnd1 opnd2 opnd3)
  1575.   (asm-M68020-proc)
  1576.   (asm-word (+ #x4c40 (opnd->mode/reg opnd1)))
  1577.   (asm-word (+ #x0800 (* (dreg-num opnd3) 4096) (dreg-num opnd2)))
  1578.   (opnd-ext-rd-long opnd1)
  1579.   (if ofile-asm?
  1580.     (emit-asm "divsll" ofile-tab (opnd-str opnd1) ","
  1581.                (opnd-str opnd2) ":" (opnd-str opnd3))))
  1582.  
  1583.  
  1584. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1585. ;
  1586. ; M68881 instructions:
  1587.  
  1588. (define (emit-fint.d    opnd1 opnd2) (emit-fop.d "int"    #x01 opnd1 opnd2))
  1589. (define (emit-fsinh.d   opnd1 opnd2) (emit-fop.d "sinh"   #x02 opnd1 opnd2))
  1590. (define (emit-fintrz.d  opnd1 opnd2) (emit-fop.d "intrz"  #x03 opnd1 opnd2))
  1591. (define (emit-fsqrt.d   opnd1 opnd2) (emit-fop.d "sqrt"   #x04 opnd1 opnd2))
  1592. (define (emit-flognp1.d opnd1 opnd2) (emit-fop.d "lognp1" #x06 opnd1 opnd2))
  1593. (define (emit-fetoxm1.d opnd1 opnd2) (emit-fop.d "etoxm1" #x08 opnd1 opnd2))
  1594. (define (emit-ftanh.d   opnd1 opnd2) (emit-fop.d "tanh"   #x09 opnd1 opnd2))
  1595. (define (emit-fatan.d   opnd1 opnd2) (emit-fop.d "atan"   #x0A opnd1 opnd2))
  1596. (define (emit-fasin.d   opnd1 opnd2) (emit-fop.d "asin"   #x0C opnd1 opnd2))
  1597. (define (emit-fatanh.d  opnd1 opnd2) (emit-fop.d "atanh"  #x0D opnd1 opnd2))
  1598. (define (emit-fsin.d    opnd1 opnd2) (emit-fop.d "sin"    #x0E opnd1 opnd2))
  1599. (define (emit-ftan.d    opnd1 opnd2) (emit-fop.d "tan"    #x0F opnd1 opnd2))
  1600. (define (emit-fetox.d   opnd1 opnd2) (emit-fop.d "etox"   #x10 opnd1 opnd2))
  1601. (define (emit-ftwotox.d opnd1 opnd2) (emit-fop.d "twotox" #x11 opnd1 opnd2))
  1602. (define (emit-ftentox.d opnd1 opnd2) (emit-fop.d "tentox" #x12 opnd1 opnd2))
  1603. (define (emit-flogn.d   opnd1 opnd2) (emit-fop.d "logn"   #x14 opnd1 opnd2))
  1604. (define (emit-flog10.d  opnd1 opnd2) (emit-fop.d "log10"  #x15 opnd1 opnd2))
  1605. (define (emit-flog2.d   opnd1 opnd2) (emit-fop.d "log2"   #x16 opnd1 opnd2))
  1606. (define (emit-fabs.d    opnd1 opnd2) (emit-fop.d "abs"    #x18 opnd1 opnd2))
  1607. (define (emit-fcosh.d   opnd1 opnd2) (emit-fop.d "cosh"   #x19 opnd1 opnd2))
  1608. (define (emit-fneg.d    opnd1 opnd2) (emit-fop.d "neg"    #x1A opnd1 opnd2))
  1609. (define (emit-facos.d   opnd1 opnd2) (emit-fop.d "acos"   #x1C opnd1 opnd2))
  1610. (define (emit-fcos.d    opnd1 opnd2) (emit-fop.d "cos"    #x1D opnd1 opnd2))
  1611. (define (emit-fgetexp.d opnd1 opnd2) (emit-fop.d "getexp" #x1E opnd1 opnd2))
  1612. (define (emit-fgetman.d opnd1 opnd2) (emit-fop.d "getman" #x1F opnd1 opnd2))
  1613. (define (emit-fdiv.d    opnd1 opnd2) (emit-fop.d "div"    #x20 opnd1 opnd2))
  1614. (define (emit-fmod.d    opnd1 opnd2) (emit-fop.d "mod"    #x21 opnd1 opnd2))
  1615. (define (emit-fadd.d    opnd1 opnd2) (emit-fop.d "add"    #x22 opnd1 opnd2))
  1616. (define (emit-fmul.d    opnd1 opnd2) (emit-fop.d "mul"    #x23 opnd1 opnd2))
  1617. (define (emit-fsgldiv.d opnd1 opnd2) (emit-fop.d "sgldiv" #x24 opnd1 opnd2))
  1618. (define (emit-frem.d    opnd1 opnd2) (emit-fop.d "rem"    #x25 opnd1 opnd2))
  1619. (define (emit-fscale.d  opnd1 opnd2) (emit-fop.d "scale"  #x26 opnd1 opnd2))
  1620. (define (emit-fsglmul.d opnd1 opnd2) (emit-fop.d "sglmul" #x27 opnd1 opnd2))
  1621. (define (emit-fsub.d    opnd1 opnd2) (emit-fop.d "sub"    #x28 opnd1 opnd2))
  1622. (define (emit-fcmp.d    opnd1 opnd2) (emit-fop.d "cmp"    #x38 opnd1 opnd2))
  1623.  
  1624. (define (emit-fop.x name code opnd1 opnd2)
  1625.   (asm-M68881-proc)
  1626.   (asm-word (+ #xf200 (opnd->mode/reg opnd1)))
  1627.   (asm-word (+ (* (if (freg? opnd1) (freg-num opnd1) #x12) 1024)
  1628.                (* (freg-num opnd2) 128)
  1629.                code))
  1630.   (opnd-ext-rd-long opnd1)
  1631.   (if ofile-asm?
  1632.     (emit-asm "f" name "x" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1633.  
  1634. (define (emit-fop.d name code opnd1 opnd2)
  1635.   (asm-M68881-proc)
  1636.   (asm-word (+ #xf200 (opnd->mode/reg opnd1)))
  1637.   (asm-word (+ #x5400 (* (freg-num opnd2) 128) code))
  1638.   (opnd-ext-rd-long opnd1)
  1639.   (if ofile-asm?
  1640.     (emit-asm "f" name "d" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1641.  
  1642. (define (emit-fmov.d opnd1 opnd2)
  1643.   (emit-fmov #x5400 opnd1 opnd2)
  1644.   (if ofile-asm?
  1645.     (emit-asm "fmoved" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1646.  
  1647. (define (emit-fmov.l opnd1 opnd2)
  1648.   (emit-fmov #x4000 opnd1 opnd2)
  1649.   (if ofile-asm?
  1650.     (emit-asm "fmovel" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))
  1651.  
  1652. (define (emit-fmov code opnd1 opnd2)
  1653.  
  1654.   (define (fmov code opnd1 opnd2)
  1655.     (asm-M68881-proc)
  1656.     (asm-word (+ #xf200 (opnd->mode/reg opnd1)))
  1657.     (asm-word (+ (* (freg-num opnd2) 128) code))
  1658.     (opnd-ext-rd-long opnd1))
  1659.  
  1660.   (if (freg? opnd2)
  1661.     (fmov code opnd1 opnd2)
  1662.     (fmov (+ code #x2000) opnd2 opnd1)))
  1663.  
  1664. (define (emit-ftest.d opnd1)
  1665.   (asm-M68881-proc)
  1666.   (asm-word (+ #xf200 (opnd->mode/reg opnd1)))
  1667.   (asm-word #x543a)
  1668.   (opnd-ext-rd-long opnd1)
  1669.   (if ofile-asm?
  1670.     (emit-asm "ftestd" ofile-tab (opnd-str opnd1))))
  1671.  
  1672. (define (emit-fbeq lbl)
  1673.   (asm-M68881-proc)
  1674.   (asm-word #xf281)
  1675.   (asm-wrel lbl 0)
  1676.   (if ofile-asm?
  1677.     (emit-asm "fbeq" ofile-tab "L" lbl)))
  1678.  
  1679. (define (emit-fbne lbl)
  1680.   (asm-M68881-proc)
  1681.   (asm-word #xf28e)
  1682.   (asm-wrel lbl 0)
  1683.   (if ofile-asm?
  1684.     (emit-asm "fbne" ofile-tab "L" lbl)))
  1685.  
  1686. (define (emit-fblt lbl)
  1687.   (asm-M68881-proc)
  1688.   (asm-word #xf294)
  1689.   (asm-wrel lbl 0)
  1690.   (if ofile-asm?
  1691.     (emit-asm "fblt" ofile-tab "L" lbl)))
  1692.  
  1693. (define (emit-fbgt lbl)
  1694.   (asm-M68881-proc)
  1695.   (asm-word #xf292)
  1696.   (asm-wrel lbl 0)
  1697.   (if ofile-asm?
  1698.     (emit-asm "fbgt" ofile-tab "L" lbl)))
  1699.  
  1700. (define (emit-fble lbl)
  1701.   (asm-M68881-proc)
  1702.   (asm-word #xf295)
  1703.   (asm-wrel lbl 0)
  1704.   (if ofile-asm?
  1705.     (emit-asm "fble" ofile-tab "L" lbl)))
  1706.  
  1707. (define (emit-fbge lbl)
  1708.   (asm-M68881-proc)
  1709.   (asm-word #xf293)
  1710.   (asm-wrel lbl 0)
  1711.   (if ofile-asm?
  1712.     (emit-asm "fbge" ofile-tab "L" lbl)))
  1713.  
  1714.  
  1715. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1716. ;
  1717. ; Operand conversion procedures:
  1718.  
  1719. (define (opnd->mode/reg opnd)
  1720.   (cond ((disp? opnd) (+ 32 (disp-areg opnd))) ; 101 rrr
  1721.         ((inx? opnd)  (+ 40 (inx-areg opnd)))  ; 110 rrr
  1722.         ((pcr? opnd)  58)                      ; 111 010
  1723.         ((imm? opnd)  60)                      ; 111 100
  1724.         ((glob? opnd) (+ 32 table-reg))        ; 101 ttt
  1725.         ((freg? opnd) 0)
  1726.         (else         opnd)))
  1727.  
  1728. (define (opnd->reg/mode opnd)
  1729.   (let ((x (opnd->mode/reg opnd)))
  1730.     (* (+ (* 8 (remainder x 8)) (quotient x 8)) 64)))
  1731.  
  1732. (define (opnd-ext-rd-long opnd) (opnd-extension opnd #f #f))
  1733.  
  1734. (define (opnd-ext-rd-word opnd) (opnd-extension opnd #f #t))
  1735.  
  1736. (define (opnd-ext-wr-long opnd) (opnd-extension opnd #t #f))
  1737.  
  1738. (define (opnd-ext-wr-word opnd) (opnd-extension opnd #t #t))
  1739.  
  1740. (define (opnd-extension opnd write? word?)
  1741.   (cond ((disp? opnd) (asm-word (disp-offset opnd)))
  1742.         ((inx? opnd)  (asm-word (+ (+ (* (inx-ireg opnd) #x1000) #x800)
  1743.                                    (modulo (inx-offset opnd) #x100))))
  1744.         ((pcr? opnd)  (asm-wrel (pcr-lbl opnd) (pcr-offset opnd)))
  1745.         ((imm? opnd)  (if word? (asm-word (imm-val opnd)) (asm-long (imm-val opnd))))
  1746.         ((glob? opnd) (if write? (asm-set-glob opnd) (asm-ref-glob opnd)))))
  1747.  
  1748.  
  1749. ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  1750. ;
  1751. ; Text representation of operands:
  1752.  
  1753. (define (opnd-str opnd) ; SUN syntax
  1754.  
  1755.   (cond ((dreg? opnd)
  1756.          (vector-ref '#("d0" "d1" "d2" "d3" "d4" "d5" "d6" "d7")
  1757.                      (dreg-num opnd)))
  1758.  
  1759.         ((areg? opnd)
  1760.          (vector-ref '#("a0" "a1" "a2" "a3" "a4" "a5" "a6" "sp")
  1761.                      (areg-num opnd)))
  1762.  
  1763.         ((ind? opnd)
  1764.          (vector-ref '#("a0@" "a1@" "a2@" "a3@"
  1765.                         "a4@" "a5@" "a6@" "sp@")
  1766.                      (areg-num (ind-areg opnd))))
  1767.  
  1768.         ((pinc? opnd)
  1769.          (vector-ref '#("a0@+" "a1@+" "a2@+" "a3@+"
  1770.                         "a4@+" "a5@+" "a6@+" "sp@+")
  1771.                      (areg-num (pinc-areg opnd))))
  1772.  
  1773.         ((pdec? opnd)
  1774.          (vector-ref '#("a0@-" "a1@-" "a2@-" "a3@-"
  1775.                         "a4@-" "a5@-" "a6@-" "sp@-")
  1776.                      (areg-num (pdec-areg opnd))))
  1777.  
  1778.         ((disp? opnd)
  1779.          (string-append (opnd-str (disp-areg opnd))
  1780.                         "@("
  1781.                         (number->string (disp-offset opnd))
  1782.                         ")"))
  1783.  
  1784.         ((inx? opnd)
  1785.          (string-append (opnd-str (inx-areg opnd))
  1786.                         "@("
  1787.                         (number->string (inx-offset opnd))
  1788.                         ","
  1789.                         (opnd-str (inx-ireg opnd))
  1790.                         ":l)"))
  1791.  
  1792.         ((pcr? opnd)
  1793.          (let ((lbl (pcr-lbl opnd))
  1794.                (offs (pcr-offset opnd)))
  1795.            (if (= offs 0)
  1796.              (string-append "L" (number->string lbl))
  1797.              (string-append "L" (number->string lbl)
  1798.                             "+" (number->string offs)))))
  1799.  
  1800.         ((imm? opnd)
  1801.          (string-append "#" (number->string (imm-val opnd))))
  1802.  
  1803.         ((glob? opnd)
  1804.          (string-append "GLOB("
  1805.                         (symbol->string (glob-name opnd))
  1806.                         ")"))
  1807.  
  1808.         ((freg? opnd)
  1809.          (vector-ref '#("fp0" "fp1" "fp2" "fp3" "fp4" "fp5" "fp6" "fp7")
  1810.                      (freg-num opnd)))
  1811.  
  1812.         ((reg-list? opnd)
  1813.          (let loop ((l (reg-list-regs opnd)) (result "[") (sep ""))
  1814.            (if (pair? l)
  1815.              (loop (cdr l) (string-append result sep (opnd-str (car l))) "/")
  1816.              (string-append result "]"))))
  1817.  
  1818.         (else
  1819.          (compiler-internal-error "opnd-str, unknown 'opnd'" opnd))))
  1820.  
  1821.  
  1822. ;==============================================================================
  1823.